/*
   Copyright 2007 Corey Tabaka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

typedef unsigned int size_t;

#asm
! void farstorew(unsigned segment, int *offset, int value);
! writes the word value  at the far pointer  segment:offset

	.define	_farstorew
_farstorew:
	mov	cx,ds
	pop	dx
	pop	ds
	pop	bx
	pop	ax
	sub	sp,*6
	mov	[bx],ax
	mov	ds,cx
	jmp	dx
#endasm

#asm
! int farreadw(unsigned segment, int *offset);

	.define _farreadw
_farreadw:
	mov	cx,ds
	pop	dx
	pop	ds
	pop	bx
	sub	sp,*4
	mov	ax,[bx]
	mov	ds,cx
	jmp	dx
#endasm

#asm
	.define _farwriteb
_farwriteb:
	mov	cx,ds
	pop	dx
	pop	ds
	pop	bx
	pop	ax
	sub	sp,*6
	movb [bx],al
	mov	ds,cx
	jmp	dx
#endasm

#asm
	.define _farreadb
_farreadb:
	mov	cx,ds
	pop	dx
	pop	ds
	pop	bx
	sub	sp,*4
	movb al,[bx]
	subb ah,ah
	mov	ds,cx
	jmp	dx
#endasm

#asm
.define _linearAddress
_linearAddress:
	push bp
	mov bp,sp
	xor ebx,ebx
	xor eax,eax
	mov bx,[bp+4]
	mov ax,ds
	shl eax,*4
	add eax,ebx
	mov edx,eax
	and eax,#$ffff
	shr edx,*16
	pop bp
	ret

#endasm

void *memcpy(void *d, void *s, size_t l) {
#ifdef BCC_AX_ASM
#asm
  mov	bx,sp
  push	di
  push	si

#ifdef PARANOID
  push	es
  push	ds	; Im not sure if this is needed, so just in case.
  pop	es
  cld
#endif

#if __FIRST_ARG_IN_AX__
  mov	di,ax		; dest
  mov	si,[bx+2]	; source
  mov	cx,[bx+4]	; count
#else
  mov	di,[bx+2]	; dest
  mov	si,[bx+4]	; source
  mov	cx,[bx+6]	; count

  mov	ax,di
#endif
  		; If di is odd we could mov 1 byte before doing word move
		; as this would speed the copy slightly but its probably
		; too rare to be worthwhile.
		; NB 8086 has no problem with mis-aligned access.

  shr	cx,#1	; Do this faster by doing a mov word
  rep
  movsw
  adc	cx,cx	; Retrieve the leftover 1 bit from cflag.
  rep
  movsb

#ifdef PARANOID
  pop	es
#endif
  pop	si
  pop	di
#endasm
#else /* ifdef BCC_AX_ASM */
   register char *s1=d, *s2=(char *)s;
   for( ; l>0; l--) *((unsigned char*)s1++) = *((unsigned char*)s2++);
   return d;
#endif /* ifdef BCC_AX_ASM */
}
